using System.Text.Json.Serialization;
using Benefactor;
using Benefactor.Models.DbModels;
using Bigway.Common;
using Bigway.Common.Filters;
using Bigway.Common.Validations;
using Microsoft.AspNetCore.ResponseCompression;
using Scalar.AspNetCore;
using Serilog;
using Serilog.Events;

const string logTemplate = "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} {SourceContext} {Level:u3}] {Message:lj}{NewLine}{Exception}";
var homeDir = Environment.CurrentDirectory;
var logsDir = Path.Combine(homeDir, "Logs");
if (!Directory.Exists(logsDir))
    Directory.CreateDirectory(logsDir);
var logFilePath = Path.Combine(logsDir, "benefator-logs.txt");
var logger = new LoggerConfiguration()
    .WriteTo.Console(outputTemplate: logTemplate)
    .WriteTo.File(
        logFilePath,
        outputTemplate: logTemplate,
        rollingInterval: RollingInterval.Day,
        fileSizeLimitBytes: 10 * 1024 * 1024,
        retainedFileCountLimit: 100,
        rollOnFileSizeLimit: true,
        shared: true,
        flushToDiskInterval: TimeSpan.FromSeconds(1))
    .Enrich.FromLogContext()
    .CreateLogger();

Log.Logger = logger;

var builder = WebApplication.CreateBuilder(args);

var configuration = builder.Configuration;
var apiKey = configuration.GetValue<string>("ApiKey")!;
ValidatorExtensions.SetApiKey(apiKey);

// Add services to the container.

var services = builder.Services;
services.AddOpenApi();
services.AddHttpClient();
services.AddSerilog();
services.AddControllers(
    options => options.Filters.Add<CustomExceptionFilter>()
).AddJsonOptions(options =>
{
    var serializerOptions = options.JsonSerializerOptions;
    serializerOptions.PropertyNamingPolicy = CommonStatics.DefaultJsonNamingPolicy;
    serializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
});

services.AddResponseCompression(options =>
{
    options.EnableForHttps = true;
    options.Providers.Add<GzipCompressionProvider>();
    options.Providers.Add<BrotliCompressionProvider>();
});

const string dbName = "benefactor";
var isProduction = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Production";
var dbFileName = isProduction ? $"{dbName}prod.db" : $"{dbName}.db";
var dbFilePath = Path.Combine(homeDir, dbFileName);

services.AddCommons(
    dbFilePath,
    dbName,
    typeof(ProductType),
    typeof(Product),
    typeof(Benefit),
    typeof(BenefitsCard),
    typeof(IssuedBenefitsCard),
    typeof(Voucher),
    typeof(BenefitsCardOrder),
    typeof(BenefitsCardOrderStatus),
    typeof(RefererCommission),
    typeof(RefererCommissionRecord),
    typeof(RefererCommissionWithdrawalRecord)
);

services.AddGeneralServices(configuration);
services.AddValidators();

var app = builder.Build();

app.UseResponseCompression();

app.UseSerilogRequestLogging(options =>
{
    // Customize the message template
    options.MessageTemplate = "Handled {RequestPath}";

    // Emit debug-level events instead of the defaults
    options.GetLevel = (_, _, _) => LogEventLevel.Debug;

    // Attach additional properties to the request completion event
    options.EnrichDiagnosticContext = (diagnosticContext, httpContext) =>
    {
        diagnosticContext.Set("RequestHost", httpContext.Request.Host.Value!);
        diagnosticContext.Set("RequestScheme", httpContext.Request.Scheme);
    };
});

app.MapScalarApiReference(); // scalar/v1
app.MapOpenApi();

app.UseHttpsRedirection();
app.UseCors(corsPolicyBuilder =>
{
    corsPolicyBuilder.AllowAnyOrigin()
        .AllowAnyMethod()
        .AllowAnyHeader();
});
app.UseAuthorization();

app.MapControllers();

logger.Information(app.Environment.IsDevelopment()
    ? "Running on development environment"
    : "Running on non-development environment");

await app.InitAndRunAsync();

public partial class Program { }
